2、EnvoyFilter API
EnvoyFilter API
目录
[toc]
本节实战
实战名称 |
---|
🚩 实战:EnvoyFilter API-全局范围-2023.12.18(测试成功) |
🚩 实战:EnvoyFilter API-配置优先级-2023.12.18(测试成功) |
🚩 实战:EnvoyFilter API-添加 Lua 脚本-2023.12.18(测试成功) |
EnvoyFilter API
前面我们介绍了可以使用 EnvoyFilter
对象来部署 Istio Wasm 插件,此外 EnvoyFilter
还可以实现很多其他的功能。EnvoyFilter
提供了一种机制来自定义 Istio Pilot 生成的 Envoy 配置,使用 EnvoyFilter 可以修改某些字段的值、添加特定过滤器,甚至添加全新的侦听器、集群等,当然我们必须谨慎使用此功能,因为不正确的配置可能会破坏整个网格的稳定性。
需要注意当多个 EnvoyFilter
绑定到指定命名空间中的相同工作负载时,所有补丁将按照创建时间的顺序依次处理,如果多个 EnvoyFilter
配置相互冲突,则会无效。要将 EnvoyFilter
资源应用于系统中的所有工作负载(sidecar 和网关),则根命名空间中定义该资源,而不使用工作负载选择器即可。
Patch 操作
在 EnvoyFilter
对象中有一个 configPatches
字段,这个字段属于核心字段,用于指定要对 Envoy 进行什么样的操作,对各种配置对象进行的更改,该字段下面主要包括三个字段:
applyTo
:指定应在 Envoy 配置中的哪个位置应用补丁。根据 applyTo 的不同,匹配条件应选择相应的对象。例如,带有HTTP_FILTER
的 applyTo 应该在监听器上有一个匹配条件,网络过滤器选择envoy.filters.network.http_connection_manager
,并在相对于插入应执行的 HTTP 过滤器上有一个子过滤器选择。类似地,对于CLUSTER
的 applyTo,如果提供了匹配条件,应该在集群上匹配,而不是在监听器上。match
:在监听器/路由配置/集群上的匹配。patch
:要应用的补丁以及操作。
其中的 applyTo
指定了在 Envoy 配置中给定的补丁应该被应用的位置,这个字段的值可以使用的值如下所示:
名称 | 描述 |
---|---|
INVALID | |
LISTENER | 将补丁应用于监听器。 |
FILTER_CHAIN | 将补丁应用于过滤器链。 |
NETWORK_FILTER | 将补丁应用于网络过滤器链,以修改现有过滤器或添加新过滤器。 |
HTTP_FILTER | 将补丁应用于 HTTP 连接管理器中的 HTTP 过滤器链,以修改现有过滤器或添加新过滤器。 |
ROUTE_CONFIGURATION | 将补丁应用于 HTTP 连接管理器内的路由配置(rds 输出)。这不适用于虚拟主机。目前,仅允许在路由配置对象上进行MERGE 操作。 |
VIRTUAL_HOST | 将补丁应用于路由配置中的虚拟主机。 |
HTTP_ROUTE | 将补丁应用于路由配置中匹配的虚拟主机内的路由对象。 |
CLUSTER | 将补丁应用于 CDS 输出中的集群。也用于添加新集群。 |
EXTENSION_CONFIG | 将补丁应用于或在 ECDS 输出中添加扩展配置。注意,ECDS 仅由 HTTP 过滤器支持。 |
BOOTSTRAP | 将补丁应用于引导配置。 |
LISTENER_FILTER | 将补丁应用于监听器过滤器。 |
根据我们的需求选择不同的 applyTo
值,然后在 match
字段中指定匹配条件,在将补丁应用于给定代理的生成配置之前,必须满足一个或多个匹配条件,match
下面可以配置的字段如下所示:
context
:匹配特定的配置的生成上下文。Istio Pilot 在网关的上下文中、sidecar 的入站流量和出站流量中生成 envoy 配置。可以配置的包括:ANY
:Sidecar 和网关中的所有侦听器/路由/集群。SIDECAR_INBOUND
:Sidecar 中的入站侦听器/路由/集群。SIDECAR_OUTBOUND
:Sidecar 中的出站侦听器/路由/集群。GATEWAY
:网关中的侦听器/路由/集群。
proxy
:匹配与代理关联的属性。listener
:匹配 envoy 监听器属性。routeConfiguration
:匹配 envoy HTTP 路由配置属性。cluster
:匹配 envoy 集群属性。
最后的 patch
字段用于指定要应用的补丁以及操作,这个字段的值可以使用的值如下所示:
operation
:指定 path 应该如何被应用,可以配置的值包括:INVALID
:无效的操作。MERGE
:将补丁与现有配置合并,如果要指定整个配置,请使用用REPLACE
。ADD
:将提供的配置添加到现有列表中(侦听器、集群、虚拟主机、网络过滤器或 HTTP 过滤器)。当applyTo
设置为ROUTE_CONFIGURATION
或HTTP_ROUTE
时,此操作将被忽略。REMOVE
:从列表(侦听器、集群、虚拟主机、网络过滤器、路由或 http 过滤器)中删除选定的对象,不需要指定value
。当applyTo
设置为ROUTE_CONFIGURATION
或HTTP_ROUTE
时,此操作将被忽略。INSERT_BEFORE
:在指定的对象之前插入提供的配置。此操作通常仅在过滤器或路由的上下文中有用,其中元素的顺序很重要。路由应根据最具体的匹配条件进行排序,因为会选择第一个匹配的元素。对于集群和虚拟主机,数组中的元素的顺序并不重要。在选择的过滤器或子过滤器之前插入。如果未选择任何过滤器,则指定的过滤器将插入到列表的最前面。INSERT_AFTER
:在指定的对象之后插入提供的配置。INSERT_FIRST
:根据所选的过滤器的存在与否,在列表中首先进行插入。当您希望根据 Match 子句中指定的匹配条件将您的过滤器排在列表的第一位时,这特别有用。REPLACE
:用新内容替换过滤器的内容。REPLACE
操作仅适用于HTTP_FILTER
和NETWORK_FILTER
。
value
:指定要应用的补丁,被修补的对象的 JSON 配置。将使用 proto 合并语义与路径中现有的 proto 进行合并。filterClass
:确定过滤器插入顺序,它与ADD
操作结合使用,如果您的过滤器依赖于或影响过滤器链中另一个过滤器的功能,则过滤器排序非常重要。在过滤器类中,过滤器按照处理顺序插入。可以配置的值包括:UNSPECIFIED
:控制平面决定在哪里插入过滤器,如果过滤器独立于其他过滤器,则不要指定FilterClass
。AUTHN
:在 Istio 身份验证过滤器之后插入过滤器。AUTHZ
:在 Istio 授权过滤器之后插入过滤器。STATS
:在 Istio 统计过滤器之前插入过滤器。
接下来我们就用几个例子再来熟悉下 EnvoyFilter
的使用。
全局范围
🚩 实战:EnvoyFilter API-全局范围-2023.12.18(测试成功)
- 测试环境
k8sv1.27.6(containerd:istiov1.19.3(--setprofile=demo)tinygoversion0.30.0
实验软件:
在上面的这个资源对象中我们重新定义了 Envoy 的的访问日志,将日志输出到标准输出中,并重新定义了日志的格式。
- 先看下默认时应用的访问日志
[root@master1 ~]#kubectl logs -f productpage-v1-564d4686f-7vhks……INFO:werkzeug:::ffff:10.244.2.18--[18/Dec/2023 11:48:32]"GET /metrics HTTP/1.1"200-INFO:werkzeug:::ffff:10.244.2.18--[18/Dec/2023 11:48:47]"GET /metrics HTTP/1.1"200-INFO:werkzeug:::ffff:10.244.2.18--[18/Dec/2023 11:49:02]"GET /metrics HTTP/1.1"200-INFO:werkzeug:::ffff:10.244.2.18--[18/Dec/2023 11:49:17]"GET /metrics HTTP/1.1"200-INFO:werkzeug:::ffff:10.244.2.18--[18/Dec/2023 11:49:32]"GET /metrics HTTP/1.1"200-
- 直接应用上面的资源对象即可:
kubectlapply-faccess-log-filter.yaml
- 然后我们可以重新访问下 Bookinfo 应用,看下是否能够看到新的日志:
exportGATEWAY_URL=$(kubectlgetpo-listio=ingressgateway-nistio-system-o'jsonpath={.items[0].status.hostIP}'):$(kubectlgetsvcistio-ingressgateway-nistio-system-o'jsonpath={.spec.ports[?(@.name=="http2")].nodePort}')curl-vhttp:# ......[2023-12-11T06:39:06.955Z] "200[2023-12-11T06:39:06.945Z] "200
从上面的结果可以看到,我们通过 EnvoyFilter 自定义的日志已经生效了。
- 同样也可以查看下其他服务的日志,比如 details 服务,正常也能看到如下所示的日志:
$kubectllogs-f$(kubectlgetpo-lapp=details-o'jsonpath={.items[0].metadata.name}') -cistio-proxy[2023-12-11T06:39:06.948Z] "200
- 其它
如果设置一个其他的命名空间,比如
default
,那么这个EnvoyFilter
就只会应用到default
命名空间中的工作负载,而不会应用到其他命名空间中的工作负载。同样再次加上工作负载选择器,那么这个EnvoyFilter
就只会应用到default
命名空间中特定的工作负载了,而不会应用到工作负载。
测试结束。😘
配置优先级
🚩 实战:EnvoyFilter API-配置优先级-2023.12.18(测试成功)
- 测试环境
k8sv1.27.6(containerd:istiov1.19.3(--setprofile=demo)tinygoversion0.30.0
实验软件:
在上面的这个资源对象中我们定义了一个 EnvoyFilter
,这个 EnvoyFilter
的优先级为 20,我们将会在 Productpage 服务中应用这个 EnvoyFilter
,这个 EnvoyFilter
的作用是在 Productpage 服务中添加一个故障注入的过滤器,当我们访问 Productpage 服务时,会全部返回 503 错误。
- 然后我们再创建一个如下所示的
EnvoyFilter
资源对象:
# priority-10-filter.yamlapiVersion:networking.istio.io/v1alpha3kind:EnvoyFiltermetadata:name:priority-10spec:workloadSelector:labels:app:productpagepriority:10configPatches:- applyTo:HTTP_FILTERmatch:context:ANYlistener:filterChain:filter:name:"envoy.filters.network.http_connection_manager"subFilter:name:"envoy.filters.http.fault"patch:operation:MERGEvalue:name:envoy.filters.http.faulttyped_config:"@type":type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFaultabort:http_status:500percentage:numerator:50denominator:HUNDRED
这个资源对象和前面的资源对象基本一样,只是将优先级设置为 10,另外将故障注入的概率都设置为 50%, 并且中断的状态码为 500。
- 接下来我们同时应用上面的两个资源对象:
kubectlapply-fpriority-10-filter.yamlkubectlapply-fpriority-20-filter.yaml
- 应用后我们再多次访问 Productpage 服务,看下会得怎样的结果:
$curl-vhttp:>GET /productpage HTTP/1.1>User-Agent:curl/7.29.0>Host:192.168.0.20:31896>Accept:*/*><HTTP/1.1 503 Service Unavailable<content-length:18<content-type:text/plain<date:Mon,11 Dec 2023 07:08:33 GMT<server:istio-envoy<x-envoy-upstream-service-time:58<
从结果看每次请求都会返回 503 错误,这是因为优先级为 10 的 EnvoyFilter
先于优先级为 20 的 EnvoyFilter
应用,所以优先级为 20 的 EnvoyFilter
覆盖了优先级为 10 的 EnvoyFilter
,这也是符合我们的预期的。
- 记得回收掉刚才创建的资源
kubectldelete-fpriority-10-filter.yamlkubectldelete-fpriority-20-filter.yaml
测试结束。😘
添加 Lua 脚本
🚩 实战:EnvoyFilter API-添加 Lua 脚本-2023.12.18(测试成功)
- 测试环境
k8sv1.27.6(containerd:istiov1.19.3(--setprofile=demo)tinygoversion0.30.0
实验软件: